/**
 * 文档转换服务
 * 功能：提供多种Word文档转换方案的统一接口
 */

import type { 
  DocumentConversionResult, 
  EditorError, 
  ErrorType 
} from '../types/word-editor'
import { ConverterType } from '../types/word-editor'

/**
 * 文档转换器类
 * 功能：统一管理不同的文档转换器
 */
export class DocumentConverter {
  private static instance: DocumentConverter
  
  /**
   * 获取单例实例
   * 功能：确保全局只有一个转换器实例
   * 返回值：DocumentConverter实例
   */
  public static getInstance(): DocumentConverter {
    if (!DocumentConverter.instance) {
      DocumentConverter.instance = new DocumentConverter()
    }
    return DocumentConverter.instance
  }
  
  /**
   * 转换文档
   * 功能：智能转换Word文档，默认使用Mammoth，失败时自动尝试docx-preview
   * 参数：file - Word文档文件
   * 参数：converterType - 转换器类型（可选，默认自动选择）
   * 返回值：转换结果Promise
   */
  public async convertDocument(
    file: File, 
    converterType?: ConverterType
  ): Promise<DocumentConversionResult> {
    try {
      // 验证文件
      this.validateFile(file)
      
      // 如果指定了转换器类型，直接使用
      if (converterType) {
        switch (converterType) {
          case ConverterType.MAMMOTH:
            return await this.convertWithMammoth(file)
          case ConverterType.DOCX_PREVIEW:
            return await this.convertWithDocxPreview(file)
          default:
            throw new Error(`不支持的转换器类型: ${converterType}`)
        }
      }
      
      // 自动回退机制：默认使用Mammoth，失败时尝试docx-preview
      try {
        console.log('尝试使用 Mammoth.js 转换文档...')
        const mammothResult = await this.convertWithMammoth(file)
        
        // 如果转换成功且有内容，返回结果
        if (mammothResult.success && mammothResult.html.trim()) {
          mammothResult.messages.unshift({
            type: 'info',
            message: '使用 Mammoth.js 转换成功'
          })
          return mammothResult
        }
        
        // 如果Mammoth转换结果为空，尝试docx-preview
        console.log('Mammoth.js 转换结果为空，尝试使用 docx-preview...')
        const previewResult = await this.convertWithDocxPreview(file)
        previewResult.messages.unshift({
          type: 'info',
          message: 'Mammoth.js 转换结果为空，已自动切换到 docx-preview'
        })
        return previewResult
        
      } catch (mammothError) {
        console.log('Mammoth.js 转换失败，尝试使用 docx-preview...', mammothError)
        
        try {
          const previewResult = await this.convertWithDocxPreview(file)
          previewResult.messages.unshift({
            type: 'info',
            message: 'Mammoth.js 转换失败，已自动切换到 docx-preview'
          })
          return previewResult
        } catch (previewError) {
          // 两个转换器都失败了
          throw new Error(`所有转换器都失败了。Mammoth错误: ${mammothError instanceof Error ? mammothError.message : '未知错误'}; docx-preview错误: ${previewError instanceof Error ? previewError.message : '未知错误'}`)
        }
      }
      
    } catch (error) {
      console.error('文档转换失败:', error)
      return {
        html: '',
        messages: [{
          type: 'error',
          message: error instanceof Error ? error.message : '未知错误'
        }],
        success: false
      }
    }
  }
  
  /**
   * 验证文件
   * 功能：检查文件是否符合要求
   * 参数：file - 要验证的文件
   */
  private validateFile(file: File): void {
    // 检查文件类型
    if (!file.name.toLowerCase().endsWith('.docx')) {
      throw this.createError(
        ErrorType.UNSUPPORTED_FORMAT,
        '仅支持.docx格式的文件'
      )
    }
    
    // 检查文件大小（限制为50MB）
    const maxSize = 50 * 1024 * 1024
    if (file.size > maxSize) {
      throw this.createError(
        ErrorType.FILE_TOO_LARGE,
        `文件大小超过限制（最大50MB），当前文件大小：${(file.size / 1024 / 1024).toFixed(2)}MB`
      )
    }
  }
  
  /**
   * 使用Mammoth.js转换文档
   * 功能：将Word文档转换为HTML格式
   * 参数：file - Word文档文件
   * 返回值：转换结果Promise
   */
  private async convertWithMammoth(file: File): Promise<DocumentConversionResult> {
    try {
      // 动态导入mammoth
      const mammoth = await import('mammoth')
      
      // 读取文件为ArrayBuffer
      const arrayBuffer = await this.fileToArrayBuffer(file)
      
      // 转换文档
      const result = await mammoth.convertToHtml({ 
        arrayBuffer,
        // 配置样式映射以保持格式
        styleMap: [
          "p[style-name='Heading 1'] => h1:fresh",
          "p[style-name='Heading 2'] => h2:fresh",
          "p[style-name='Heading 3'] => h3:fresh",
          "p[style-name='Title'] => h1.title:fresh",
          "r[style-name='Strong'] => strong",
          "r[style-name='Emphasis'] => em"
        ]
      })
      
      return {
        html: this.enhanceHtml(result.value),
        messages: result.messages.map(msg => ({
          type: msg.type as 'warning' | 'error' | 'info',
          message: msg.message
        })),
        success: true
      }
    } catch (error) {
      throw this.createError(
        ErrorType.CONVERSION_FAILED,
        `Mammoth转换失败: ${error instanceof Error ? error.message : '未知错误'}`
      )
    }
  }
  
  /**
   * 使用docx-preview转换文档
   * 功能：使用docx-preview库预览文档
   * 参数：file - Word文档文件
   * 返回值：转换结果Promise
   */
  private async convertWithDocxPreview(file: File): Promise<DocumentConversionResult> {
    try {
      // 动态导入docx-preview
      const { renderAsync } = await import('docx-preview')
      
      // 创建临时容器
      const container = document.createElement('div')
      container.style.position = 'absolute'
      container.style.left = '-9999px'
      document.body.appendChild(container)
      
      try {
        // 渲染文档
        await renderAsync(file, container, undefined, {
          className: 'docx-preview-container',
          inWrapper: true,
          ignoreWidth: false,
          ignoreHeight: false,
          ignoreFonts: false,
          breakPages: true,
          ignoreLastRenderedPageBreak: true,
          experimental: false,
          trimXmlDeclaration: true,
          useBase64URL: false,
          useMathMLPolyfill: false,
          showChanges: false,
          debug: false
        })
        
        const html = container.innerHTML
        
        return {
          html: this.enhanceHtml(html),
          messages: [],
          success: true
        }
      } finally {
        // 清理临时容器
        document.body.removeChild(container)
      }
    } catch (error) {
      throw this.createError(
        ErrorType.CONVERSION_FAILED,
        `docx-preview转换失败: ${error instanceof Error ? error.message : '未知错误'}`
      )
    }
  }
  
  /**
   * 文件转ArrayBuffer
   * 功能：将File对象转换为ArrayBuffer
   * 参数：file - 文件对象
   * 返回值：ArrayBuffer Promise
   */
  private fileToArrayBuffer(file: File): Promise<ArrayBuffer> {
    return new Promise((resolve, reject) => {
      const reader = new FileReader()
      reader.onload = () => resolve(reader.result as ArrayBuffer)
      reader.onerror = () => reject(new Error('文件读取失败'))
      reader.readAsArrayBuffer(file)
    })
  }
  
  /**
   * 增强HTML内容
   * 功能：为转换后的HTML添加样式和结构优化
   * 参数：html - 原始HTML内容
   * 返回值：增强后的HTML内容
   */
  private enhanceHtml(html: string): string {
    // 添加表格边框样式
    let enhancedHtml = html.replace(
      /<table/g, 
      '<table style="border-collapse: collapse; width: 100%; margin: 12pt 0;"'
    )
    
    // 添加单元格样式
    enhancedHtml = enhancedHtml.replace(
      /<(th|td)([^>]*)>/g,
      '<$1$2 style="border: 1px solid #000; padding: 4pt 8pt; text-align: left;">'
    )
    
    // 优化段落间距
    enhancedHtml = enhancedHtml.replace(
      /<p([^>]*)>/g,
      '<p$1 style="margin: 0 0 12pt 0;">'
    )
    
    // 优化标题样式
    enhancedHtml = enhancedHtml.replace(
      /<(h[1-6])([^>]*)>/g,
      '<$1$2 style="margin: 18pt 0 12pt 0; font-weight: bold;">'
    )
    
    return enhancedHtml
  }
  
  /**
   * 创建错误对象
   * 功能：创建标准化的错误对象
   * 参数：type - 错误类型
   * 参数：message - 错误消息
   * 返回值：Error对象
   */
  private createError(type: ErrorType, message: string): Error {
    const error = new Error(message)
    ;(error as any).type = type
    return error
  }
}

/**
 * 导出默认转换器实例
 */
export const documentConverter = DocumentConverter.getInstance()